<template>
  <div class="home">
    {{ fullpath || "未查询到，请检查数据" }}
    <ToolBar :visualData="props.visualData" @backMainPage="backMainPage" @saveTemplData="saveTemplData" />
    <main>
      <!-- 左侧组件列表 -->
      <section :class="leftList ? 'left active' : 'left inactive'">
        <ComponentList />
        <RealTimeComponentList />
      </section>
      <px-button title="show-list-btn" class="btn show-list left-btn" :icon="leftList ? ArrowLeft : ArrowRight" @click="isShowLeft" />
      <!-- 中间画布 -->
      <section class="center" :style="rightList ? 'margin-right:288px' : 'margin-right:10px'">
        <div class="content" @drop="handleDrop" @dragover="handleDragOver" @mousedown="handleMouseDown" @mouseup="deselectCurComponent">
          <Editor />
        </div>
      </section>
      <!-- 右侧属性列表 -->
      <section :class="rightList ? 'right active' : 'right inactive'">
        <px-tabs v-if="curComponent" v-model="activeName" @tab-click="tabClick">
          <px-tab-pane label="属性" name="attr">
            <component :is="curComponent.component + 'Attr'" />
          </px-tab-pane>
          <!-- <px-tab-pane label="动画" name="animation" style="padding-top: 20px">
            <AnimationList />
          </px-tab-pane> -->
          <px-tab-pane label="事件" name="events">
            <EventList />
          </px-tab-pane>
          <px-tab-pane label="数据管理" name="datas">
            <DataBinding v-if="showDataBinding" :visual-data="props.visualData" />
          </px-tab-pane>
        </px-tabs>
      </section>
      <px-button title="show-list-btn" class="btn show-list right-btn" :icon="rightList ? ArrowRight : ArrowLeft" @click="isShowRight" />
    </main>
  </div>
</template>
<script setup lang="ts">
import "@visual/assets/iconfont/iconfont.css";

// import AnimationList from "../components/AnimationList.vue";
import ComponentList from "@visual/components/ComponentList.vue";
import Editor from "@visual/components/Editor/Editor.vue";
import EventList from "@visual/components/EventList.vue";
import DataBinding from "@visual/components/DataBinding.vue";
import RealTimeComponentList from "@visual/components/RealTimeComponentList.vue";
import ToolBar from "@visual/components/ToolBar.vue";
import componentList from "@visual/custom-component/component-list";
import { cloneDeep } from "@pureadmin/utils";
import { nanoid } from "nanoid";
import { useComponent, useContextMenu, useCompose, useSnapshot, setDefaultcomponentData } from "@visual/stores";

import { storeToRefs } from "pinia";
import { listenGlobalKeyDown } from "@visual/utils";
import { ref, toRaw, watch, provide, inject, computed } from "vue";
import { ArrowLeft, ArrowRight } from "@px-ui/icons-vue";

defineOptions({
  // name 作为一种规范最好必须写上并且和路由的name保持一致
  name: "VisualEditer"
});

provide("isVisualEditer", true);
const currentTree = inject("curTreeData", ref({}));
const positionCode = inject("positionCode", ref(""));
const fullpath = computed(() => {
  const cur = currentTree.value[positionCode.value];
  let res = [];
  if (cur && cur.path) {
    let pathArr = cur.path?.split("@");
    if (pathArr && pathArr.length > 0) {
      pathArr.forEach(item => {
        if (currentTree.value[item]) {
          const { name } = currentTree.value[item];
          res.push(name);
        }
      });
    }
  }
  return res.join("/");
});

const props = defineProps({
  visualData: {
    type: Array,
    default: () => []
  },
  visualConfig: {
    type: Object || null,
    default: null
  }
});
const emits = defineEmits(["backMainPage", "saveTemplData"]);

const leftList = ref(true);

// 右侧画布
const activeName = ref("attr");
const componentStore = useComponent();
const { curComponent, rightList, componentData } = storeToRefs(componentStore);
const { isShowRightList } = componentStore;
const showDataBinding = ref(false);
function isShowLeft() {
  leftList.value = !leftList.value;
}
function isShowRight() {
  isShowRightList();
}
function backMainPage() {
  emits("backMainPage");
}
function saveTemplData() {
  emits("saveTemplData", toRaw(componentData.value));
}
// 全局监听按键事件
listenGlobalKeyDown();
function tabClick(panel) {
  if (panel.paneName === "datas") {
    showDataBinding.value = true;
  } else {
    showDataBinding.value = false;
  }
}
function handleDrop(e: DragEvent) {
  e.preventDefault();
  e.stopPropagation();
  let index: string = "";
  if (e.dataTransfer) index = e.dataTransfer.getData("index");

  const { editor } = useCompose();
  const rectInfo = editor!.getBoundingClientRect();
  if (index !== "") {
    const component = cloneDeep(componentList[+index]);
    component.style.top = e.clientY - rectInfo.y;
    component.style.left = e.clientX - rectInfo.x;
    component.id = nanoid();

    // // 根据画面比例修改组件样式比例 https://github.com/woai3c/visual-drag-demo/issues/91
    // changeComponentSizeWithScale(component);
    const componentStore = useComponent();
    componentStore.addComponent({ component });

    console.log("@@@Drop: ", component.style.top, component.style.left);
    const { recordSnapshot } = useSnapshot();
    recordSnapshot();
  }
}

function handleDragOver(e: DragEvent) {
  e.preventDefault();
  // 拖动鼠标手型
  if (e.dataTransfer) e.dataTransfer.dropEffect = "copy";
}

function handleMouseDown(e: MouseEvent) {
  e.stopPropagation();
  const { setClickComponentStatus, setInEditorStatus } = useComponent();
  setClickComponentStatus(false);
  setInEditorStatus(true);
}

function deselectCurComponent(e: MouseEvent) {
  const componentStore = useComponent();
  const { isClickComponent } = storeToRefs(componentStore);
  const { hideContextMenu } = useContextMenu();

  if (!isClickComponent.value) {
    componentStore.setCurComponent({ component: null, index: null });
  }
  // 0 左击 1 滚轮 2 右击
  if (e.button != 2) {
    hideContextMenu();
  }
}

function restore() {
  const { setComponentData, setCanvasStyle } = componentStore;
  // 用保存的数据恢复画布
  // const canvasData = localStorage.getItem("canvasData");
  const canvasData = props.visualConfig;
  // const canvasStyle = localStorage.getItem("canvasStyle");
  if (canvasData && canvasData.json) {
    // setDefaultcomponentData(JSON.parse(canvasData));
    const components = cloneDeep(componentList);
    let json = JSON.parse(canvasData.json);
    updateArrayObjects(json, components, "component");
    setComponentData(json);
  } else {
    setComponentData([]);
  }

  // if (canvasStyle) {
  //   setCanvasStyle(canvasStyle);
  // }
}
function flattenObject(obj, key) {
  let result = {};
  // 如果 obj 是数组，递归处理每个元素
  if (Array.isArray(obj)) {
    return obj.map(item => flattenObject(item, key));
  }

  // 如果是对象，按 key 进行扁平化
  for (let prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      if (prop === key) {
        // 找到扁平化的 key
        result[key] = obj[prop];
      } else {
        result[prop] = obj[prop];
      }
    }
  }
  return result;
}

function updateObject(obj1, obj2) {
  // 遍历 obj2 中的键
  for (let key in obj2) {
    if (obj2.hasOwnProperty(key)) {
      // 如果 obj1 中没有该 key，则直接添加
      if (!(key in obj1)) {
        obj1[key] = obj2[key];
      } else {
        // 如果 obj2[key] 是对象且 obj1[key] 也是对象，递归更新
        if (typeof obj2[key] === "object" && obj2[key] !== null) {
          if (typeof obj1[key] !== "object" || obj1[key] === null) {
            obj1[key] = {}; // 如果 obj1[key] 不是对象，则初始化为空对象
          }
          updateObject(obj1[key], obj2[key]); // 递归更新子对象
        }
      }
    }
  }
  return obj1;
}
function updateArrayObjects(obj1, obj2, key) {
  // 首先扁平化 obj2
  const flattenedObj2 = obj2.map(item => flattenObject(item, key));

  // 遍历 obj1
  obj1.forEach(item1 => {
    // 查找对应的 obj2 中的模板对象
    const matchedTemplate = flattenedObj2.find(item2 => item2[key] === item1[key]);

    if (matchedTemplate) {
      // 对于找到的模板，更新 obj1 中对应的对象
      updateObject(item1, matchedTemplate);
    }
    if (item1[key] === "Group" && item1.propValue && item1.propValue.components && item1.propValue.components.length > 0) {
      const components = item1.propValue.components;
      components.forEach(comp => {
        const matchedTemplate = flattenedObj2.find(item2 => item2[key] === comp[key]);
        if (matchedTemplate) {
          // 对于找到的模板，更新 obj1 中对应的对象
          updateObject(comp, matchedTemplate);
        }
      });
    }
  });

  return obj1;
}

watch(
  () => props.visualConfig,
  newVal => {
    restore();
  },
  {
    immediate: true
  }
);
// onCreated
// restore();
</script>
<style lang="scss" scoped>
.home {
  // height: 100vh;
  height: calc(100vh - 145px);
  background: #fff;

  /* 定义滚动条高宽及背景
 高宽分别对应横竖滚动条的尺寸 */
  ::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }

  /* 定义滚动条轨道
  内阴影+圆角 */
  ::-webkit-scrollbar-track {
    background-color: transparent;
  }

  /* 定义滑块
  内阴影+圆角 */
  ::-webkit-scrollbar-thumb {
    background-color: #ddd;
    border-radius: 4px;
  }

  .tool-bar {
    padding: 0 15px 10px;
    overflow-x: auto;
    white-space: nowrap;
    background: #fff;
    border-bottom: 1px solid #ddd;
  }

  main {
    position: relative;
    height: calc(100% - 64px);

    .show-list {
      position: absolute;
      top: 40%;
      z-index: 9;
      transition: all 0.3s;
    }

    .left-btn,
    .right-btn {
      color: #606266;
      background: #fff;
      border: 1px;
    }

    .left-btn {
      padding: 9px 4px 9px 2px;
      margin-left: 200px;
      border-radius: 0 50% 50% 0;
    }

    .right-btn {
      right: 0;
      padding: 9px 2px 9px 4px;
      margin-right: 288px;
      border-radius: 50% 0 0 50%;
    }

    .left {
      position: absolute;
      top: 0;
      left: 0;
      width: 200px;
      height: 100%;

      & > div {
        overflow: auto;

        &:first-child {
          border-bottom: 1px solid #ddd;
        }
      }
    }

    .left.inactive {
      width: 10px;
      overflow: hidden;

      div {
        opacity: 0;
      }
    }

    .left.inactive ~ .center,
    .left.inactive ~ .btn.left-btn {
      margin-left: 10px;
    }

    .right {
      position: absolute;
      top: 0;
      right: 0;
      width: 288px;
      height: 100%;

      .px-select {
        width: 100%;
      }
      // 右侧attr编辑列表样式
      .attr-list {
        height: 100%;
        padding: 10px 14px;
        padding-top: 0;
        overflow: auto;
      }

      .px-collapse-item__content {
        padding-bottom: 0;
      }

      .v-common-attr {
        margin-bottom: 18px;

        .px-form {
          padding: 10px;
          padding-top: 0;
        }
      }

      .px-tabs {
        height: 100%;
      }

      .px-tabs__content {
        height: calc(100% - 55px);
        overflow: auto;
      }

      .px-tabs__nav-scroll {
        padding-left: 20px;
      }

      .px-tabs__header {
        margin: 0;
      }

      .px-tag {
        text-align: right;
      }
    }

    .right.inactive {
      width: 10px;
      overflow: hidden;

      div {
        opacity: 0;
      }
    }

    .right.inactive ~ .btn.right-btn {
      margin-right: 10px;
    }

    .center {
      height: 100%;
      padding: 20px;
      margin-right: 288px;
      margin-left: 200px;
      overflow: auto;
      background: #f5f5f5;

      .content {
        width: 100%;
        height: 100%;
        overflow: auto;
      }
    }
  }

  .placeholder {
    color: #333;
    text-align: center;
  }

  .global-attr {
    padding: 10px;
  }
}

:deep(.attr-list) {
  height: 650px !important;
}
</style>
